package Hot100;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * @author zhangmin
 * @create 2022-01-08 14:07
 */
public class coinChange322 {
    /**
     * 322. 零钱兑换
     * 给你一个整数数组 coins ，表示不同面额的硬币；以及一个整数 amount ，表示总金额。
     * 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额，返回 -1 。你可以认为每种硬币的数量是无限的。
     * 回溯：---超时
     * 路径：已选择的列表
     * 选择列表：当前金额的硬币选或者不选
     * 终止条件：达到amount，选择到了列表的最后一个
     * */
    LinkedList<List<Integer>> res=new LinkedList<>();
    void backtrack(int[] coins,int index,int amount,LinkedList<Integer> path){
        if (amount==0){
            res.add(new LinkedList<>(path));
            return;
        }
        if (index==coins.length||amount<0) return;
        //1、选择要当前的硬币,可以重复选择
        path.add(coins[index]);
        backtrack(coins,index,amount-coins[index],path);
        path.removeLast();
        //2、选择不要当前的硬币，去选择下一个
        backtrack(coins,index+1,amount,path);
    }
    public int coinChange1(int[] coins, int amount) {
        backtrack(coins,0,amount,new LinkedList<>());
        int resnum=Integer.MAX_VALUE;
        for (List<Integer> list: res) {
            resnum=Math.min(resnum,list.size());
        }
        return resnum==Integer.MAX_VALUE?-1:resnum;
    }

    /*2、dp
    * dp[i]表示当目标金额为i时，至少需要多少个硬币
    *  dp[i] = Math.min( 1 + dp[i - coin]);coin是coins中的任意值
    * */
    public int coinChange(int[] coins, int amount) {
        int[]dp=new int[amount+1];
        Arrays.fill(dp,amount+1);
        dp[0]=0;
        for (int i = 0; i < amount+1; i++) {
            for (int coin:coins) {
                if (i-coin<0) continue;
                dp[i]=Math.min(dp[i],dp[i-coin]+1);
            }
        }
        return dp[amount]==amount+1?-1:dp[amount];
    }
}
